package com.qixiaobao.direct.invoice.service.impl;

import com.qixiaobao.common.core.domain.model.LoginUser;
import com.qixiaobao.common.exception.UtilException;
import com.qixiaobao.common.utils.SecurityUtils;
import com.qixiaobao.common.utils.StringUtils;
import com.qixiaobao.common.utils.easyExcel.EasyExcelUtil;
import com.qixiaobao.direct.invoice.domain.dto.DirectInvoiceDTO;
import com.qixiaobao.direct.invoice.domain.vo.DirectInvoiceChargeVO;
import com.qixiaobao.direct.invoice.domain.vo.DirectInvoiceVO;
import com.qixiaobao.direct.invoice.domain.vo.DirectWaitInvoiceVO;
import com.qixiaobao.direct.invoice.mapper.DirectInvoiceNewMapper;
import com.qixiaobao.direct.invoice.service.IDirectInvoiceNewService;
import com.qixiaobao.system.domain.Dict;
import com.qixiaobao.system.domain.SlaveUser;
import com.qixiaobao.system.mapper.DictMapper;
import com.qixiaobao.system.mapper.SlaveUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @Description 直投发票管理（新）  业务层处理
 * @Author yangxm
 * @Date 2025/7/3 15:32
 */
@Slf4j
@Service
public class DirectInvoiceNewServiceImpl implements IDirectInvoiceNewService {

    @Autowired
    private DirectInvoiceNewMapper directInvoiceNewMapper;
    @Autowired
    private DictMapper dictMapper;
    @Autowired
    private SlaveUserMapper slaveUserMapper;

    /**
     * @Description 查询待开票列表
     * @Author yangxm
     * @Date 2025/7/3 15:35
     * @param directInvoiceDTO
     * @return java.util.List<com.qixiaobao.directinvoice.domain.vo.DirectWaitInvoiceVO>
     */
    @Override
    public List<DirectWaitInvoiceVO> selectWaitInvoiceList(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        log.info("查询直投发票管理(新)-待开票列表，参数：{}", directInvoiceDTO);
        List<DirectWaitInvoiceVO> list = directInvoiceNewMapper.selectWaitInvoiceList(directInvoiceDTO);
        log.info("查询直投发票管理(新)-待开票列表sql，耗时：{}ms", System.currentTimeMillis() - begin);
        if (StringUtils.isNotEmpty(list)){
            //字典
            Map<String, String> invoiceTypeMap = dictMapper.selectDictListByType("invoice_type").stream().
                    collect(Collectors.toMap(Dict::getK, Dict::getVal));
            //客服信息
            Map<Long, String> usernameMap = slaveUserMapper.selectUsernameList().stream()
                    .collect(Collectors.toMap(SlaveUser::getId, SlaveUser::getUsername));

            DirectWaitInvoiceVO item;
            for (int i = 0; i < list.size(); i++) {
                item = list.get(i);
                item.setInvoiceTypeVal(invoiceTypeMap.get(item.getInvoiceType()));
                item.setServiceName(usernameMap.getOrDefault(item.getServiceId(), ""));
            }
        }
        log.info("查询直投发票管理(新)-待开票列表完成，总耗时：{}ms", System.currentTimeMillis() - begin);
        return list;
    }

    /**
     * @Description 待开票 - 开票金额合计
     * @Author yangxm
     * @Date 2025/7/3 16:00
     * @param directInvoiceDTO
     * @return java.math.BigDecimal
     */
    @Override
    public BigDecimal selectWaitInvoiceTotal(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        BigDecimal waitInvoiceTotal = BigDecimal.ZERO;
        log.info("查询直投发票管理(新)-待开票-开票金额合计，参数：{}", directInvoiceDTO);
        List<DirectWaitInvoiceVO> list = directInvoiceNewMapper.selectWaitInvoiceList(directInvoiceDTO);
        if (StringUtils.isNotEmpty(list)){
            waitInvoiceTotal = list.stream().map(DirectWaitInvoiceVO::getInsureFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        log.info("查询直投发票管理(新)-待开票列表-开票金额合计完成，总耗时：{}ms", System.currentTimeMillis() - begin);
        return waitInvoiceTotal;
    }

    /**
     * @Description 开票中、已开票 - 列表
     * @Author yangxm
     * @Date 2025/7/3 16:06
     * @param directInvoiceDTO
     * @return java.util.List<com.qixiaobao.directinvoice.domain.vo.DirectInvoiceVO>
     */
    @Override
    public List<DirectInvoiceVO> selectInvoiceList(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        if (directInvoiceDTO.getInvoiceStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureStatusVal = "1".equals(directInvoiceDTO.getInvoiceStatus()) ? "开票中" : "2".equals(directInvoiceDTO.getInvoiceStatus()) ? "已开票" : "";
        if (StringUtils.isBlank(insureStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("查询直投发票管理(新)-{}列表，参数：{}", insureStatusVal, directInvoiceDTO);
        List<DirectInvoiceVO> list = directInvoiceNewMapper.selectInvoiceList(directInvoiceDTO);
        log.info("查询直投发票管理(新)-{}列表sql，耗时：{}ms", insureStatusVal, System.currentTimeMillis() - begin);
        if (StringUtils.isNotEmpty(list)){
            //字典
            Map<String, String> invoiceTypeMap = dictMapper.selectDictListByType("invoice_type").stream().
                    collect(Collectors.toMap(Dict::getK, Dict::getVal));
            //客服信息
            Map<Long, String> usernameMap = slaveUserMapper.selectUsernameList().stream()
                    .collect(Collectors.toMap(SlaveUser::getId, SlaveUser::getUsername));

            DirectInvoiceVO item;
            for (int i = 0; i < list.size(); i++) {
                item = list.get(i);
                item.setInvoiceTypeVal(invoiceTypeMap.get(item.getInvoiceType()));
                item.setServiceName(usernameMap.getOrDefault(item.getServiceId(), ""));
            }
        }
        log.info("查询直投发票管理(新)-{}列表完成，总耗时：{}ms", insureStatusVal, System.currentTimeMillis() - begin);
        return list;
    }

    /**
     * @Description 开票中、已开票 - 列表 - 开票金额总计
     * @Author yangxm
     * @Date 2025/7/3 16:32
     * @param directInvoiceDTO
     * @return java.math.BigDecimal
     */
    @Override
    public BigDecimal selectInvoiceTotal(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        BigDecimal invoiceTotal = BigDecimal.ZERO;
        if (directInvoiceDTO.getInvoiceStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureStatusVal = "1".equals(directInvoiceDTO.getInvoiceStatus()) ? "开票中" : "2".equals(directInvoiceDTO.getInvoiceStatus()) ? "已开票" : "";
        if (StringUtils.isBlank(insureStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("查询直投发票管理(新)-{}-开票金额总计，参数：{}", insureStatusVal, directInvoiceDTO);
        List<DirectInvoiceVO> list = directInvoiceNewMapper.selectInvoiceList(directInvoiceDTO);
        if (StringUtils.isNotEmpty(list)){
            invoiceTotal = list.stream().map(DirectInvoiceVO::getInsureFee).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        log.info("查询直投发票管理(新)-{}-开票金额总计完成，总耗时：{}ms", insureStatusVal, System.currentTimeMillis() - begin);
        return invoiceTotal;
    }

    /**
     * @Description 开票中、已开票 - 导出
     * @Author yangxm
     * @Date 2025/7/3 16:39
     * @param directInvoiceDTO
     * @param response
     */
    @Override
    public void invoiceExport(DirectInvoiceDTO directInvoiceDTO, HttpServletResponse response) {
        long begin = System.currentTimeMillis();
        if (directInvoiceDTO.getInvoiceStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureStatusVal = "1".equals(directInvoiceDTO.getInvoiceStatus()) ? "开票中" : "2".equals(directInvoiceDTO.getInvoiceStatus()) ? "已开票" : "";
        if (StringUtils.isBlank(insureStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("导出直投发票管理(新)-{}列表，参数：{}", insureStatusVal, directInvoiceDTO);
        String fileName = "直投发票管理(新)-" + insureStatusVal + "列表";
        List<String> arrayHeaders = new ArrayList<>();
        arrayHeaders.add("序号");
        if("1".equals(directInvoiceDTO.getInvoiceStatus())){
            arrayHeaders.add("税号");
        }
        arrayHeaders.add("发票编号");
        if("1".equals(directInvoiceDTO.getInvoiceStatus())){
            arrayHeaders.add("公司注册地址");
            arrayHeaders.add("公司注册电话");
            arrayHeaders.add("开户银行");
            arrayHeaders.add("银行账号");
        }
        arrayHeaders.add("供应商全称");
        arrayHeaders.add("供应商简称");
        arrayHeaders.add("付款单位");
        arrayHeaders.add("开票金额");
        arrayHeaders.add("发票类型");
        arrayHeaders.add("客服");
        arrayHeaders.add("开票时间");
        arrayHeaders.add("操作时间");
        arrayHeaders.add("备注");
        //动态表头
        List<List<String>> headList = new ArrayList<>();
        String headStr;
        List<String> headArray;
        for (int i = 0; i < arrayHeaders.size(); i++) {
            headStr = arrayHeaders.get(i);
            headArray = new ArrayList<>();
            headArray.add(headStr);
            headList.add(headArray);
        }
        List<DirectInvoiceVO> list = selectInvoiceList(directInvoiceDTO);
        //动态表头的数据
        List<List<Object>> datalist = new ArrayList<>();
        List<Object> obj = null;
        DirectInvoiceVO  item;
        for (int j = 0; j < list.size(); j++) {
            item = list.get(j);
            obj = new ArrayList<>();
            obj.add(j + 1);

            if(directInvoiceDTO.getInsureProofStatus() == 0){
                obj.add(item.getTaxNum());
            }
            obj.add(item.getInvoiceNo());
            if(directInvoiceDTO.getInsureProofStatus() == 0){
                obj.add(item.getCompanyAddress());
                obj.add(item.getCompanyPhone());
                obj.add(item.getBankName());
                obj.add(item.getBankNum());
            }
            obj.add(item.getSupplyName());
            obj.add(item.getSupplyShortName());
            obj.add(item.getCustomerName());
            obj.add(item.getInsureFee());
            obj.add(item.getInvoiceTypeVal());
            obj.add(item.getServiceName());
            obj.add(Optional.ofNullable(item.getCreateTime()).map(x-> DateFormatUtils.format(x, "yyyy/MM/dd HH:mm:ss")).orElse(""));
            obj.add(Optional.ofNullable(item.getUpdateTime()).map(x-> DateFormatUtils.format(x, "yyyy/MM/dd HH:mm:ss")).orElse(""));
            obj.add(item.getSupplyRemark());
            datalist.add(obj);
        }
        try {
            EasyExcelUtil.writeExcel(response, datalist, headList, fileName, fileName);
        } catch (IOException e) {
            log.error(" {}导出异常：", fileName, e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
        log.info("导出直投发票管理(新)-{}列表完成，总耗时：{}", insureStatusVal, System.currentTimeMillis() - begin);
    }

    /**
     * @Description 开票中、已开票 - 详情
     * @Author yangxm
     * @Date 2025/7/3 16:51
     * @param invoiceId
     * @return java.util.List<com.qixiaobao.directinvoice.domain.vo.DirectInvoiceChargeVO>
     */
    @Override
    public List<DirectInvoiceChargeVO> selectInvoiceChargeListByInvoiceId(Long invoiceId) {
        long begin = System.currentTimeMillis();
        log.info("直投发票管理-开票中、已开票-费用详情，参数：{}", invoiceId);
        List<DirectInvoiceChargeVO> list = directInvoiceNewMapper.selectInvoiceChargeListByInvoiceId(invoiceId);
        log.info("直投发票管理-开票中、已开票-费用详情列表sql，耗时：{}ms", System.currentTimeMillis() - begin);
        if (StringUtils.isNotEmpty(list)){
            //字典
            List<Dict> dictList = dictMapper.selectDictList();
            Map<String, Map<String, String>> dictMap = new ConcurrentHashMap<>();
            if (StringUtils.isNotEmpty(dictList)) {
                dictMap = dictList.stream()
                        .filter(c -> c.getVal() != null)
                        .collect(Collectors.groupingBy(Dict::getType, Collectors.toMap(Dict::getK, Dict::getVal)));
            }
            Map<String, String> mealNameMap = dictMap.getOrDefault("mealName", new ConcurrentHashMap<>());
            Map<String, String> insurePeriodMap = dictMap.getOrDefault("insureperiod", new ConcurrentHashMap<>());
            Map<String, String> insureTypeMap = dictMap.getOrDefault("insuretype", new ConcurrentHashMap<>());
            Map<String, String> jobTypeMap = dictMap.getOrDefault("jobtype", new ConcurrentHashMap<>());
            //客服信息
            Map<Long, String> usernameMap = slaveUserMapper.selectUsernameList().stream()
                    .collect(Collectors.toMap(SlaveUser::getId, SlaveUser::getUsername));

            DirectInvoiceChargeVO item;
            for (int i = 0; i < list.size(); i++) {
                item = list.get(i);
                item.setIndex(i + 1);
                item.setServiceName(usernameMap.getOrDefault(item.getServiceId(), ""));
                item.setMeanNameVal(mealNameMap.getOrDefault(item.getMealName(), ""));
                item.setInsureTypeVal(insureTypeMap.getOrDefault(item.getInsureType(), ""));
                item.setInsurePeriodVal(insurePeriodMap.getOrDefault(item.getInsurePeriod(), ""));
                item.setJobTypeVal(jobTypeMap.getOrDefault(item.getJobType(), ""));
                item.setInsurePerson("增员:" + item.getAddNum() + ";减员:" + item.getMinusNum());
            }

        }
        return list;
    }

    /**
     * @Description 开票中 - 修改供应商备注
     * @Author yangxm
     * @Date 2025/7/3 17:18
     * @param directInvoiceDTO
     * @return int
     */
    @Override
    public int updateSupplyRemark(DirectInvoiceDTO directInvoiceDTO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new IllegalArgumentException("获取登录信息失败，请重新登录！");
        }
        //添加备注操作人
        directInvoiceDTO.setSupplyRemarkOperator(loginUser.getUsername());
        return directInvoiceNewMapper.updateSupplyRemark(directInvoiceDTO);
    }

    /**
     * @Description 开票中 - 上传发票文件
     * @Author yangxm
     * @Date 2025/7/3 17:25
     * @param directInvoiceDTO
     * @return int
     */
    @Override
    public int uploadInvoiceFile(DirectInvoiceDTO directInvoiceDTO) {
        return directInvoiceNewMapper.updateInvoiceFile(directInvoiceDTO);
    }

    /**
     * @Description 查询发票文件
     * @Author yangxm
     * @Date 2025/7/3 17:25
     * @param directInvoiceDTO
     * @return java.lang.String
     */
    @Override
    public String selectInvoiceFile(DirectInvoiceDTO directInvoiceDTO) {
        return directInvoiceNewMapper.selectInvoiceFile(directInvoiceDTO);
    }
}
